`include "../define.svh"
(* use_dsp48 = "no", use_carry_chain = "yes" *)
module round_add (
    //input clk,
    //input sys_rst_n,
    input signed [8:0] e_norm,
    input [27:0] m_norm,        // 输入28位尾数（含隐含位和舍入位）
    input [1:0] data_type,       // 数据类型：FP16/FP32/INT
    output [8:0] e_out,      // 舍入后的指数
    output [23:0] m_rnd_o   // 舍入后的尾数（含隐含位）
    //output reg underflow         // 下溢出标志
);


//--------------------------
// 并行计算所有可能路径的信号
//--------------------------
// 公共信号
wire is_denormal;
wire [8:0] shift_amount;
assign is_denormal = (e_norm < 9'sd1);
assign shift_amount = 9'sd1 - e_norm;

// FP16路径信号
wire [27:0] m_shifted;
wire [10:0] fp16_round_bits;
wire guard_bit_fp16;
wire sticky_bit_fp16;
wire round_up_fp16;
wire [11:0] fp16_rounded;
wire fp16_overflow;
wire [8:0] e_adjusted_fp16;
wire [23:0] m_adjusted_fp16;
wire [23:0] m_denormal_fp16;

assign m_shifted = m_norm >> shift_amount;
assign fp16_round_bits = is_denormal ? m_shifted[27:17] : m_norm[27:17];
assign guard_bit_fp16 = is_denormal ? m_shifted[16] : m_norm[16];
assign sticky_bit_fp16 = |(is_denormal ? m_shifted[15:0] : m_norm[15:0]);
assign round_up_fp16 = guard_bit_fp16 & (sticky_bit_fp16 | fp16_round_bits[0]);
assign fp16_rounded = {1'b0, fp16_round_bits} + round_up_fp16;
assign fp16_overflow = fp16_rounded[11];
assign e_adjusted_fp16 = is_denormal ? 9'd0 : (e_norm + fp16_overflow);
assign m_adjusted_fp16 = fp16_overflow ? {14'b0, fp16_rounded[11:1]} : {14'b0, fp16_rounded[10:0]};
assign m_denormal_fp16 = {13'd0, m_shifted[27:17]};

// FP32路径信号
wire [23:0] fp32_round_bits;
wire guard_bit_fp32;
wire sticky_bit_fp32;
wire round_up_fp32;
wire [24:0] fp32_rounded;
wire fp32_overflow;
wire [8:0] e_adjusted_fp32;
wire [23:0] m_adjusted_fp32;
wire [23:0] m_denormal_fp32;

assign fp32_round_bits = is_denormal ? m_shifted[27:4] : m_norm[27:4];
assign guard_bit_fp32 = is_denormal ? m_shifted[3] : m_norm[3];
assign sticky_bit_fp32 = |(is_denormal ? m_shifted[2:0] : m_norm[2:0]);
assign round_up_fp32 = guard_bit_fp32 & (sticky_bit_fp32 | fp32_round_bits[0]);
assign fp32_overflow = fp32_rounded[24];
assign e_adjusted_fp32 = is_denormal ? 9'd0 : (e_norm + fp32_overflow);
assign m_adjusted_fp32 = fp32_overflow ? fp32_rounded[24:1] : fp32_rounded[23:0];
assign m_denormal_fp32 = m_shifted[27:4];
assign fp32_rounded = {1'b0, fp32_round_bits} + round_up_fp32;

/* //--------------------------------------------------
// 使用CARRY8原语构建25位加法器（UltraScale优化）
//--------------------------------------------------
//wire [24:0] fp32_rounded;  // 25位输出（24位和 + 1位进位）
wire [3:0] carry_chain;     // 进位链信号（每个CARRY8处理8位）
// 初始进位输入为 round_up_fp32
assign carry_chain[0] = round_up_fp32;

// 第一个CARRY8：处理低8位 [7:0]
CARRY8 #(.CARRY_TYPE("SINGLE_CY8")) carry8_inst0 (
  .CO(carry_chain[1]),               // 进位输出到下一级
  .O(fp32_rounded[7:0]),               // 低8位和输出
  .CI(carry_chain[0]),                 // 初始进位输入
  .DI(fp32_round_bits[7:0]),           // 数据输入
  .S(fp32_round_bits[7:0])             // 和输入
);

// 第二个CARRY8：处理中间8位 [15:8]
CARRY8 #(.CARRY_TYPE("SINGLE_CY8")) carry8_inst1 (
  .CO(carry_chain[2]),               // 进位输出到下一级
  .O(fp32_rounded[15:8]),              // 中间8位和输出
  .CI(carry_chain[1]),                 // 来自低8位的进位
  .DI(fp32_round_bits[15:8]),          // 数据输入
  .S(fp32_round_bits[15:8])            // 和输入
);

// 第三个CARRY8：处理高8位 [23:16]
CARRY8 #(.CARRY_TYPE("SINGLE_CY8")) carry8_inst2 (
  .CO(carry_chain[3]),               // 进位输出到下一级
  .O(fp32_rounded[23:16]),             // 高8位和输出
  .CI(carry_chain[2]),                 // 来自中间8位的进位
  .DI(fp32_round_bits[23:16]),         // 数据输入
  .S(fp32_round_bits[23:16])           // 和输入
);

// 额外处理第25位（最高位）
assign fp32_rounded[24] = carry_chain[3]; // 第25位由最后一级CARRY8的最高进位决定

 */
//--------------------------
// 最终结果选择逻辑
//--------------------------
wire [8:0] e_adjusted;
wire [23:0] m_adjusted;
wire [23:0] m_denormal;

assign e_adjusted = 
    (data_type == `FP16) ? e_adjusted_fp16 :
    (data_type == `FP32) ? e_adjusted_fp32 : 9'd0;

assign m_adjusted = 
    (data_type == `FP16) ? m_adjusted_fp16 :
    (data_type == `FP32) ? m_adjusted_fp32 : 24'd0;

assign m_denormal = 
    (data_type == `FP16) ? m_denormal_fp16 :
    (data_type == `FP32) ? m_denormal_fp32 : 24'd0;

        assign e_out = e_adjusted;
        assign m_rnd_o = is_denormal ? m_denormal : m_adjusted;

/* //--------------------------
// 输出寄存（单级寄存器）
//--------------------------
always @(posedge clk or negedge sys_rst_n) begin
    if (!sys_rst_n) begin
        e_out <= 9'd0;
        m_rnd_o <= 24'd0;
        underflow <= 1'b0;
    end else begin
        e_out <= e_adjusted;
        m_rnd_o <= is_denormal ? m_denormal : m_adjusted;
        underflow <= is_denormal;
    end
end */

endmodule